// 演示最早版本的使用方法。
package main

import (
	"bytes"
	"io/fs"
	"log"
	"net"
	"os"

	"gitee.com/rocket049/gobstream"
)

func main() {
	l, err := net.Listen("tcp", "0.0.0.0:9876")
	if err != nil {
		panic(err)
	}
	defer l.Close()
	for {
		conn, err := l.Accept()
		if err != nil {
			log.Println(err.Error())
			continue
		}
		stream1 := gobstream.NewStreamConn(conn)
		serveStream(stream1)
		conn.Close()
	}
}

var files = make(map[uint32]*os.File)
var datas = make(map[uint32]*bytes.Buffer)

func serveStream(stream *gobstream.StreamConn) error {
	for {
		data, err := stream.Recv()
		if err != nil {
			return err
		}
		switch data.Typ {
		case gobstream.TypFileHead:
			// recv file header with session
			fp, err := os.Create(data.Name)
			if err != nil {
				log.Println(err.Error())
			} else {
				fp.Chmod(fs.FileMode(data.Mode))
				files[data.Session] = fp
			}
			continue
		case gobstream.TypFileData:
			yes, end, data1, err := data.GetFileData()
			if end {
				// file with session is end
				err := files[data.Session].Close()
				if err != nil {
					log.Println("filedata 1:" + err.Error())
				}
				delete(files, data.Session)
			} else if yes {
				// recv data of file with session
				if err != nil {
					log.Println("filedata 2:" + err.Error())
				} else {
					_, err = files[data.Session].Write(data1)
					if err != nil {
						log.Println("filedata 3:" + err.Error())
					}
				}
			}
			continue
		case gobstream.TypStream:
			s, err := data.GetString()
			if err != nil {
				log.Println(err.Error())
			} else if data.Status == gobstream.StatusAlone {
				// recv alone data with session
				err = stream.SendString(data.Session, "Reply:"+s, false)
				if err != nil {
					log.Println(err.Error())
				}
			} else if data.Status == gobstream.StatusStart {
				// recv first block of multi part data with session
				datas[data.Session] = bytes.NewBufferString(s)
			} else if data.Status == gobstream.StatusEnd {
				// end multi part data with session
				err = stream.SendString(data.Session, "Reply:"+datas[data.Session].String(), false)
				if err != nil {
					log.Println(err.Error())
				}
				delete(datas, data.Session)
			} else if data.Status == gobstream.StatusEmpty {
				datas[data.Session].WriteString(s)
			}
			continue
		}
	}
}
